// LicenseSvr.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include "ActiveSocket.h"
#include "PassiveSocket.h"
#include "apHTTPProxy.h"

#include <windows.h>
#include <stdio.h>
#include <Tlhelp32.h>
#include "apFilelog.h"
#pragma comment(lib, "ws2_32.lib")//wsock32.lib

SERVICE_STATUS ServiceStatus; 
SERVICE_STATUS_HANDLE hStatus; 
DWORD g_listenPID;

void ServiceMain(int argc, char** argv); 
void ControlHandler(DWORD request); 
int InitService();
bool Install();
bool Uninstall();
void usage();

const char* proxy_ip_addr	=	"192.168.81.167";//"61.152.108.187";
const int	proxy_port		=	8089;
const char* szServiceName	=  "neuroLicense";

int _tmain(int argc, _TCHAR* argv[])
{
	SERVICE_TABLE_ENTRY ServiceTable[2];
	ServiceTable[0].lpServiceName = (LPSTR)szServiceName;
	ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

	ServiceTable[1].lpServiceName = NULL;
	ServiceTable[1].lpServiceProc = NULL;

	apLog::init("C:\\log\\neuroLicense.log");

	usage();
	if(argc > 1)
	{
		if (strcmp(argv[1], "/install") == 0)
		{
			Install();
		}
		else if (strcmp(argv[1], "/uninstall") == 0)
		{
			Uninstall();
		}
		return 0;
	}

	// Start the control dispatcher thread for our service
	StartServiceCtrlDispatcher(ServiceTable); 

	return 0;
}

bool Install()
{
	SC_HANDLE hSCM, hService;
	TCHAR szPathName[MAX_PATH] = {0};
	::GetModuleFileName(NULL, szPathName, _MAX_PATH);

	hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	hService = ::CreateService(
		hSCM, szServiceName, szServiceName,
		SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
		SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
		szPathName, NULL, NULL, _T(""), NULL, NULL);

	::CloseServiceHandle(hService);
	::CloseServiceHandle(hSCM);
	printf("service %s installed\n", szServiceName);
	return true;
}

bool Uninstall()
{
	SC_HANDLE hSCM, hService;
	SERVICE_STATUS status;

	hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	OpenService(hSCM, szServiceName, SERVICE_STOP | DELETE);
	ControlService(hService, SERVICE_CONTROL_STOP, &status);
	DeleteService(hService);
	::CloseServiceHandle(hService);
	::CloseServiceHandle(hSCM);
	printf("service %s uninstalled\n", szServiceName);
	return true;
}



// Service initialization
int InitService() 
{ 
	apLog::print(0,apLog::info,"neuroLicense service started.");
	return 0; 
}

void ServiceMain(int argc, char** argv) 
{ 
	int error; 

	ServiceStatus.dwServiceType = 
		SERVICE_WIN32; 
	ServiceStatus.dwCurrentState = 
		SERVICE_START_PENDING; 
	ServiceStatus.dwControlsAccepted   =  
		SERVICE_ACCEPT_STOP | 
		SERVICE_ACCEPT_SHUTDOWN;
	ServiceStatus.dwWin32ExitCode = 0; 
	ServiceStatus.dwServiceSpecificExitCode = 0; 
	ServiceStatus.dwCheckPoint = 0; 
	ServiceStatus.dwWaitHint = 0; 

	hStatus = RegisterServiceCtrlHandler(
		"neuroLicense", 
		(LPHANDLER_FUNCTION)ControlHandler); 
	if (hStatus == (SERVICE_STATUS_HANDLE)0) 
	{ 
		// Registering Control Handler failed
		return; 
	}  
	// Initialize Service 
	error = InitService(); 
	if (error) 
	{
		// Initialization failed
		ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
		ServiceStatus.dwWin32ExitCode = -1; 
		SetServiceStatus(hStatus, &ServiceStatus); 
		return; 
	} 

	// We report the running status to SCM. 
	ServiceStatus.dwCurrentState = SERVICE_RUNNING; 
	SetServiceStatus (hStatus, &ServiceStatus);

	apHTTPProxy proxy;
	if(!proxy.Init(proxy_ip_addr, proxy_port))
	{
		apLog::print(0, apLog::error, "failed to start proxy");
		ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
		ServiceStatus.dwWin32ExitCode = -1; 
		SetServiceStatus(hStatus, &ServiceStatus); 
		return;
	}
	// The worker loop of a service
	while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
	{
		if(!proxy.is_running())
			break;
		Sleep(1000);
	}

	apLog::print(0, apLog::info, "neuroLicense service exited");
	return; 
}

void ControlHandler(DWORD request) 
{ 
	switch(request) 
	{ 
	case SERVICE_CONTROL_STOP: 
	case SERVICE_CONTROL_SHUTDOWN: 
		ServiceStatus.dwWin32ExitCode = 0; 
		ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
		SetServiceStatus (hStatus, &ServiceStatus);
		return;    
	default:
		break;
	} 

	// Report current status
	SetServiceStatus (hStatus, &ServiceStatus);

	return; 
}

void usage()
{
	printf("This program runs as service.\n");
	printf("\tTo register service run: LicenseSvr.exe /install\n"
		"\tTo unregister service run: LicenseSvr.exe /uninstall\n");
}